
\section{孤立日程系统的第二阶段功能}
\label{sec:function-2ndlevel}


第二阶段功能的目标是，帮助用户了解总体日程状态，并向用户提出建议，如：应该优先完成哪些任务。

为了实现目标，主要需要以下三个主要技术功能
\begin{enumerate}
\item
自动任务安排

\item
日程表可行性判断、日程松紧度评价

\item
下一步行动、日程优化
\end{enumerate}
为了提高这三个功能的结果的准确性，引入了可用时间、工作效率、软边界、代价模型、概率模型等概念。

第二阶段的功能是计算密集型的，计算量相比第一阶段提高了至少2个数量级，个人估计可能是3-4个数量级，
其带来的功能也是革命性的，对于强烈依赖日程系统的用户来说，可以秒杀所有其他日程系统，包括那些基于GTD理论的。
或者应该说这部分功能和GTD是不冲突的，甚至是正交的。

\subsection{自动任务安排}

在前面的提到的提醒、预约都是有具体时间的，
可以直接显示在日程表上\footnote{提醒一般不用于日程表显示，但可以在上面显示为一条线。}，
但任务只有Deadline，没有指定真正的开始时间，这也就没法显示在日程表上，
这时的日程表其实是一个未完成的日程表。但一般生活中这种待办列表的方式我们很常用，
是因为我们是每次从列表中挑出一个任务来完成，每次都是根据实际情况来安排日程表中的一项，
一天过完的时候，日程表也完成了，日程表的完成和工作的完成是同步的。
对于一般用户来说，这足够了。

但在某些时候，我们需要排出一个完整的日程表，或者排出所有可能的日程表。
这时候我们并不是真的要按照这个日程表来要求自己完全按照它生活，只是想获得一些日程表中的信息，
例如我们能否排出一个日程表？在某一个时间段内事件是否紧张？
当日程系统的模型足够复杂时，程序也许可以真的排出一个可以用来指导生活的日程表，
但由于用户的行为和实际情况是时刻变化的，真正能给用户提供直接指导的往往只是日程表中的前几项。
但为了实现其他复杂功能，排出一个或所有的日程表是必需的。

其实我们很少需要所有的日程表，一般来说只是考虑满足一定条件的日程表（如足够好的，这里的“好”将在后面定义），
这时就可以按照一定的方式对整个日程表空间进行遍历，直到产生所有我们需要的日程表即可。

孤立系统的日程表是有特殊性的，即孤立日程系统只有一个用户，那么其实就只有一个时间轴，
所有的事件最后都要不重复地安排在时间轴上。一般的日程系统不考虑
休息时间\footnote{休息时间往往较短，而且开始时刻和持续长度都是不确定的，
对于传统日程系统来说把它作为环境突然变化是较为合适的方案。但在后面将会提到一个时间粒度
是5分钟的日程系统，在那个日程系统中就不能无视休息的存在了。}，
优先完成所有任务的一个必要条件就是尽量去除事件之间的空隙，
这样我们就只需要让事件一个挨一个地紧密排列（当然要满足它们各自属性限制）即可。
而且在产生日程表时，我们其实需要的是一段足够长的时间内的日程安排，这个时间长度是有限的，
那么在这段时间内的所有事件和所有排列也是有限的，这就为遍历，甚至寻找最优安排成为可能。

在后面我们将要引入代价模型，这样所有的日程安排都可以计算出相对应的代价，
对于尚未完成安排的的部分日程表，可以估计它的可能代价，这样就可以使用A*算法寻找代价最小的日程安排，
在代价模型的前提下，这种方法是可行的。


\subsection{可用时间及工作效率}

在本文中考虑的是一个全天的日程系统，即涵盖了工作生活娱乐等一切事件的日程系统，
那么在这个日程系统中睡觉、吃饭也占据了日程表上的一部分，这就需要定义那些时间是用来完成
工作方面的事件的，哪些是家庭的等等，这就是所谓的可用时间。

可用时间的一个最简单实现就是规定8:00-17:00是工作时间，17:00-21:00是家庭时间，其余不做安排。
当然这太粗糙了，可以针对星期，假日等等进行特殊设置。

有一个问题是，我们一天的工作效率不是一成不变的，有的人早上效率高，
有人的是夜猫子，对于同样的工作量，在不同时间的完成效率不同。
这个效率可以认为是和时间绑定的，可以临时调整，如某天早上起来发现睡眠质量不好，一天晕乎乎的。
也可以对效率进行细化，如工作的效率、思考的效率、娱乐的效率、干琐事的效率等等……总之越来越复杂。

可用时间模型其实可以作为工作效率模型的特化，即把不可用的时间段的效率置为0或负数。
这样如果日程安排算法支持工作效率模型，就可以避开在这段时间安排任务。

不过即使如此，工作效率模型仍然达不到令人满意的效果（尚未实践过，只是个人预测），
一般还需要下面介绍的软边界和代价模型。

\subsection{软边界与代价模型}

既然说到软边界，那相对应的就有硬边界，
本文中的硬边界指的是前面说的Deadline，工作时间的开始和结束时刻等时间边界。
在前面的模型中，这些时间边界都是不能逾越的，所以称为硬边界。
但实际情况往往不是这样，任务也可以延期，更一般的情况是我们希望任务尽可能早地被完成，
而不是等到Deadline的时候才完成。对于可用时间段的表述就更是如此，
加班这类情况其实是很常见的，日程系统应该考虑这种情况。

但硬边界应该如何软化呢？如果仅仅是在Deadline上加上一个可选延迟，
那对于排班算法而言，原始的Deadline就没有任何意义的，直接用更晚的Deadline即可，
这不符合我们的预期。更好的模型是，我们可以把任务延迟，但要为此额外付出“代价”，
最终我们希望的是总代价最小。同样我们也可以推迟工作时间的结束时间，
但这里我们也要“付出代价”\footnote{可以认为是心理上的不爽或是家庭上的压力。}。
这样就给了排班算法一个弹性的调整空间，使得最后的结果不会太生硬。

这个代价应该如何度量呢？个人认为一个合适的单位是时间，就好象你拖延了一个任务，要为此多付出多少时间的代价。
这样有一个好处就是可以把正常的任务完成也引入代价的概念，
这个代价就是这个任务所占用的时间段内的时间的代价\footnote{可以认为不同时间段的代价是不同的}。
这样完成一个日程表的总代价就可以认为是工作量的一个近似度量。
这个总代价不光和任务的总长度有关，还与完成它们所占用的具体时间段有关。

\subsection{概率模型}

概率模型的引入是为了描述实际生活中的任务长度，
显然对于不是特别熟悉的工作，想要精确地估计所需要的时间是很难的，
虽然我们可以把任务长度设置为最坏情况，所有的任务都被设置为最坏情况会严重影响我们对日程松紧度的预期。
而如果我们把任务长度设置为所有情况的平均长度，甚至最好情况的长度，
那么日程系统所提示的日程松紧度以及任务能否完成的情况，
其实就没有考虑到任务遇到坏情况的风险。

为了把这个风险也考虑进来，最好的办法就是引入概率模型，
认为任务需要的时间是随机的，满足给定的某个分布，这个分布和任务长度有关，或者由用户直接指定。
之后就涉及到我们认为任务的完成时间应该服从什么分布的问题，想要精确的获得这个信息，
需要对这类任务的历史完成情况进行分析，只有在日程系统积累的历史信息足够多的时候才可用。

这里介绍一个简化模型来处理这种情况，即用户指定某个任务在最好情况、平均情况、最坏情况的完成时间，
并分别给出他们的的概率。这样的参数较容易指定，特别是配合有参数模板之后，
从内核来考虑，每个任务平均只有三种状态，搜索所有状态也是可能的。
当然也可以使用连续模型，或是对输入概率表进行连续性平滑，但排班的时候就涉及到抽样，
抽样点的数目就成了不小的问题。

概率模型也可以用于其他方面，如把资源的可用性、工作效率等等其他概念也进行随机化，
但这些内容应该有什么样的意义和什么样的特性则需要仔细考虑。


\subsection{关于任务分割}

任务分割是一个很另类的需求，指的是日程系统在安排任务时，
可以对长任务进行适当分割，使之可以被合适地安排在日程中。

任务分割问题涉及到应该把任务分为多少段，每段多长，
如何选择合适的方式使之适合当前的日程安排，
这其中涉及到的参数和约束较多，
具体将在 \ref{sec:detail-schedule.task-partition} 节进行讨论。
可以看作是更高级的日程需求，笑。


\subsection{日程可行性判定和日程松紧评价}

\subsubsection{日程可行性判定}

可行性判定的重要性这里就不进行介绍，主要介绍判断方法。

可行性判定问题在数学上可以看作是约束可行性的问题，
赋予每个事件一个时间位置变量，要求不同的事件不能重合，
并且满足该事件的各种属性要求和日程系统中的其他附属要求，
最后得到一组线性不等式组，对于某些问题说不定会出现非线性的不等式\footnote{我没能想出来这种情况。}。
可以采用线性规划算法来判定，不过由于一些可数资源的存在可能会引入部分整数变量，给求解带来困难。

除了线性规划算法外，还可以尝试SMT（Satisfiability Modulo Theories）\footnote{
Wiki\href{http://en.wikipedia.org/wiki/Satisfiability_Modulo_Theories}{\emph{传送门}}。}。
从功能上来说，SMT应该更能满足要求，而且当出现冲突时可以给出最小冲突集，
可以告诉用户是哪些约束（事件）导致日程不可行。\footnote{线性规划应该也能给出冲突集，我对此不了解。}
但现阶段SMT求解器的可用性还不好，尚处于学术界研究的阶段。

当然还可以按照前面说的直接搜索日程安排空间，除了效率问题外，
当出现冲突时该方法也无法给出最小冲突集。

需要说明的是上面的方法严格上来讲不适用于任意的任务分割情况，因为被分割的段数可以任意多，
相当于需要引入任意多的变量，线性规划方法不适用，SMT的某些高级功能可能是可用的。
但实际上，我们可以规定一个最大分割段数$M$，这样就可以采用上面的方法求解，
但变量数量增大了$M$倍。

\subsubsection{日程松紧评价}

松紧评价是可行性判定问题的推广，但这个需求的具体算法实现是不明确的。
首先日程的松紧性应该和所考虑的时间有关的，可能有一段时间很闲，而另一段时间很忙。
而时间并不固定的任务的工作量应该被平均在所有可用的时间上，不同的任务可能分布的时间段是不同的。

这方面需要进一步分析用户需求。可行的方案应该包括暴力法：枚举所有状态并统计相关的时间信息。

\subsection{下一步行动}
\label{sec:function-2ndlevel.nextstep}

下一步行动是指当用户空闲时，系统根据当前日程状态向用户推荐几个任务完成，
需要注意的是，虽然系统可以推荐多个任务，但用户每次只从中选出一个来完成，
完成或部分完成后会再次要求系统进行评估并推荐。

推荐任务的标准应该是以某些目标来讲，达到了最优或较优，这些目标可以是
\begin{enumerate}
  \item 当前可行的任务中优先级最高的。
  \item 当前可行的任务中，没能完成的概率最大的，即最可能会被拖后并超过Deadline的。
  \item 如果给未来一段时间按的日程规定一个定量的松紧性指标，则是可以最大限度地减小该指标的任务。
  \item 如果使用了代价模型，则可以是最大限度地减小任务的完成代价的任务。
  按代价对所有日程方案进行排序，代价最小的日程方案的第一个任务。
  \item ……
\end{enumerate}
也可以是以上某些指标的某种加权。

这样求得可以当前最适合进行的任务，还有稍微差些的任务，
向用户推荐前3项，之所以选择3项是出于用户体验的考虑，当然这个数字可以由用户自己进行设置。
太少了用户可选的余地太小，感到受约束；太多了则会有一种要做的任务好多的想法，同样不适合。

该功能和用户手工从日程系统中的可行任务列表中手工挑选的主要区别有：
\begin{enumerate}
  \item 频繁地查看全部任务，并从大量不适合做的任务中挑出一个想做的任务很烦人（亲身感觉），
    而且有的时候选择过多反而会延长决策时间。
  \item 由于上一条的原因，用户一般只查看较短时间内的可行任务，但可能由于任务见复杂的逻辑依赖和时间冲突问题
    导致某些虽然Deadline很晚的任务需要被显著地提前完成，而简单的按时间过滤任务会导致用户漏过这类任务，
    给日程的完成带来风险。
    
  \item 前面引入的一些复杂模型如可数资源、软边界、可用时间等等的问题会明显增加用户手工选择最优任务的难度，
    最后容易变成仅仅选择当前最喜欢的任务，而不是最应该做的任务。特别是人都有偷懒的心理。
  
  \item 在引入概率模型后，手工选择最优任务几乎是不可能的。
\end{enumerate}

\subsection{日程优化}

日程优化相当于是下一步行动的扩展，下一步行动只关注下一个任务或是几个任务的安排，
考虑的时间段较短，而日程优化是在一段较长的时间内对日程安排进行优化，
寻找较优安排甚至最优安排。

虽然和下一步行动比起来，这个功能似乎没有什么用处，因为往往只有日程安排的第一项是对的，
后面的安排会随着时间的延长而逐渐偏离实际。但生成实际日程安排仍然是有必要的，
例如在
\begin{enumerate}
\item 日程公开
\item 用户想要查看/了解未来某一时间的情况
\item 打印出来脱机使用
\item 遍历所有实际日程安排统计一些不容易计算的参数
\end{enumerate}

总的来说，日程优化是很复杂的，目前我只能想到搜索的方法。



